package com.panda.admin.login.auth.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.panda.admin.base.BaseEnum;
import com.panda.admin.constant.RegularConstants;
import com.panda.admin.feign.InterfacesFeign;
import com.panda.admin.feign.LoginFeign;
import com.panda.admin.login.access.service.SystemUserRoleService;
import com.panda.admin.login.auth.controller.SystemUserController;
import com.panda.admin.login.auth.mapper.SystemUserMapper;
import com.panda.admin.login.auth.service.SystemUserService;
import com.panda.admin.login.config.LoginInfoUtil;
import com.panda.admin.login.dto.LoginDto;
import com.panda.admin.login.dto.PasswordDto;
import com.panda.admin.login.dto.RegisterDto;
import com.panda.admin.login.entity.SystemCaptcha;
import com.panda.admin.login.entity.SystemLog;
import com.panda.admin.login.entity.SystemUser;
import com.panda.admin.login.entity.SystemUserRole;
import com.panda.admin.result.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
* @author tucy123
* @description 针对表【system_user(用户表)】的数据库操作Service实现
* @createDate 2022-10-27 09:26:47
*/
@Service
public class SystemUserServiceImpl extends ServiceImpl<SystemUserMapper, SystemUser> implements SystemUserService {

    @Autowired
    SystemUserMapper systemUserMapper;

    @Autowired
    SystemUserRoleService systemUserRoleService;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    SystemUserController systemUserController;

    @Autowired
    LoginFeign loginFeign;

    @Autowired
    InterfacesFeign interfacesFeign;

    /**
     * 系统注册
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SystemUser register(RegisterDto dto) {
        //校验账号
        boolean matches = dto.getAccount().matches(RegularConstants.IS_digit_letter);
        if (!matches){
            throw new ServiceException("账号必须为数字或字母");
        }
        SystemUser systemUser = this.lambdaQuery().eq(SystemUser::getAccount, dto.getAccount()).one();
        if (ObjectUtil.isNotEmpty(systemUser)){
            throw new ServiceException("账号已注册");
        }
        //创建根系统账户
        SystemUser user = new SystemUser();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        String now = format.format(new Date());
        user.setAccount(dto.getAccount());
        user.setPassword(passwordEncoder.encode(dto.getPassword()));
        user.setNickname(now);
        user.setLevelId(systemUserMapper.queryDefaultLevel());
        this.saveOrUpdate(user);

        //绑定角色
        SystemUserRole userRole = new SystemUserRole();
        userRole.setUserId(user.getId());
        userRole.setRoleId(dto.getRoleId());
        systemUserRoleService.save(userRole);

        //保存日志
        SystemLog log = new SystemLog();
        log.setOperator(dto.getAccount());
        log.setOperation("新用户注册");
        log.setParams(JSONUtil.toJsonStr(dto));
        log.setMethod("com.panda.admin.login.auth.service.impl.SystemUserServiceImpl.register");
        log.setIpAddress(LoginInfoUtil.getIpAddress());
        interfacesFeign.saveLogs(log);

        return user;
    }

    /**
     * 密文密码
     * @param word
     * @return
     */
    @Override
    public String encryption(String word) {
        return passwordEncoder.encode(word);
    }

    /**
     * 运算保存验证码
     * @param captcha
     */
    @Override
    public void mathSaveCaptcha(String captcha,String uuid) {
        SystemCaptcha systemCaptcha = new SystemCaptcha();
        systemCaptcha.setUuid(uuid);
        systemCaptcha.setExpireTime(this.getDate());
        systemCaptcha.setCreateTime(new Date());
        systemCaptcha.setCommonStatus(BaseEnum.NORMAL.getValue());
        if (captcha.contains("=")){
            String retouch = this.retouch(captcha.replace(" ",""));
            systemCaptcha.setCaptcha(retouch);
        }else {
            systemCaptcha.setCaptcha(captcha);
        }
        systemUserMapper.mathSaveCaptcha(systemCaptcha);
    }

    /**
     * 后台登录
     * @param loginDto
     * @return
     */
    @Override
    public Object manageLogin(LoginDto loginDto) {
        //校验验证码
        List<SystemCaptcha> captchaList = systemUserMapper.checkCaptcha(loginDto.getUuid(),loginDto.getCaptcha());
        if (ObjectUtil.isEmpty(captchaList) || captchaList.size() != 1){
            //失败：重新登录
            throw new ServiceException("验证码错误");
        }
        //成功：删除验证码
        systemUserMapper.deleteCaptcha(loginDto.getUuid());

        //登录
        Map<String, String> params = new HashMap<String, String>();
        params.put("client_id", "client");
        params.put("client_secret", "secret");
        params.put("grant_type", "password");
        params.put("username", loginDto.getUsername());
        params.put("password", loginDto.getPassword());
        Object data = loginFeign.postAccessToken(params).getData();

        //保存日志
        SystemLog log = new SystemLog();
        log.setOperator(loginDto.getUsername());
        log.setOperation("后台登录");
        log.setParams(JSONUtil.toJsonStr(loginDto));
        log.setMethod("com.panda.admin.login.auth.service.impl.SystemUserServiceImpl.manageLogin");
        log.setIpAddress(LoginInfoUtil.getIpAddress());
        interfacesFeign.saveLogs(log);

        return data;
    }

    /**
     * 处理验证码
     * @param captcha
     */
    private String retouch(String captcha) {
        String substr = captcha.substring(0,captcha.indexOf("="));
        BigDecimal decimal;
        try {
            if (substr.contains("+")){
                String[] split = substr.split("\\+");
                decimal = new BigDecimal(split[0]).add(new BigDecimal(split[1]));
            } else if (substr.contains("-")){
                String[] split = substr.split("\\-");
                decimal = new BigDecimal(split[0]).subtract(new BigDecimal(split[1]));
            } else if (substr.contains("*")){
                String[] split = substr.split("\\*");
                decimal = new BigDecimal(split[0]).multiply(new BigDecimal(split[1]));
            } else {
                String[] split = substr.split("\\/");
                decimal = new BigDecimal(split[0]).divide(new BigDecimal(split[1]));
            }
            return decimal.toString();
        }catch (Exception e){
            throw new ServiceException("生成验证码失败,请重试!");
        }
    }

    /**
     * 验证码有效时间
     * @return
     */
    private Date getDate(){
        Calendar cal = Calendar.getInstance();
        long currentTimeMillis = cal.getTimeInMillis();
        long tenMinutesLaterMillis = currentTimeMillis + 1800000;
        cal.setTimeInMillis(tenMinutesLaterMillis);
        return cal.getTime();
    }

    /**
     * 定时任务，删除过期的验证码
     */
    @Scheduled(cron = "0 0 0 * * ?")
    private void deleteExpireCaptcha(){
        Boolean result = systemUserMapper.deleteExpireCaptcha();
        log.debug(result?"删除验证码成功":"删除验证码失败");
    }

    /**
     * 修改密码
     * @param passwordDto
     * @return
     */
    @Override
    public String updatePassword(PasswordDto passwordDto) {
        SystemUser user = this.lambdaQuery().eq(SystemUser::getAccount, passwordDto.getAccount()).one();
        boolean matches = passwordEncoder.matches(passwordDto.getPassword(), user.getPassword());
        if (!matches){
            throw new ServiceException("原密码不正确");
        }
        passwordDto.setNewPassword(passwordEncoder.encode(passwordDto.getNewPassword()));
        boolean result = systemUserMapper.updatePassword(passwordDto);

        return result ? "修改成功" : "修改失败";
    }
}
